package me.qi.kancha.applet;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import me.qi.kancha.mapper.WxAppMapper;
import me.qi.kancha.dto.core.WxAppDTO;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 小程序登录
 *
 * @author 孙阳
 * @date 2020/10/30 11:24
 */
@Component
public class AppletLoginSdk {

    private static final Logger log = LoggerFactory.getLogger(AppletLoginSdk.class);

    private final DataStore dataStore;

    private final RestTemplateBuilder restTemplateBuilder;

    private final WxAppMapper wxAppMapper;

    public AppletLoginSdk(DataStore dataStore,
                          RestTemplateBuilder restTemplateBuilder,
                          WxAppMapper wxAppMapper) {
        this.dataStore = dataStore;
        this.restTemplateBuilder = restTemplateBuilder;
        this.wxAppMapper = wxAppMapper;
    }

    /**
     * 小程序登录
     *
     * @param code
     * @return
     */
    public WXUserInfo appletLogin(String appId,String code) {
        String appSecret = getAppSecret(appId);
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid={1}&secret={2}&js_code={3}&grant_type=authorization_code";
        String str = restTemplateBuilder.build().getForObject(url, String.class, appId, appSecret, code);
        Map<String, Object> result = new Gson().fromJson(str, Map.class);
        if (!isSuccess(result)) {
            String message = String.format("小程序%s jscode2session登录失败:%s", appId, result.toString());
            log.error(message);
            throw new RuntimeException(message);
        }
        String openid = (String) result.get("openid");
        String sessionKey = (String) result.get("session_key");
        String unionid = (String) result.get("unionid");
        dataStore.storeSessionKey(appId, openid, sessionKey);
        return new WXUserInfo(openid, unionid);
    }

    /**
     * 从数据库&redis获取 appSecret
     * @param appId
     * @return
     */
    public String getAppSecret(String appId) {
        String secret = dataStore.readSecret(appId);
        if (secret == null) {
            LambdaQueryWrapper<WxAppDTO> qw = new LambdaQueryWrapper<>();
            WxAppDTO wxAppDTO = wxAppMapper.selectOne(qw.eq(WxAppDTO::getAppId, appId));
            if (wxAppDTO == null) {
                throw new RuntimeException("未注册appid");
            }
            secret = wxAppDTO.getAppSecret();
            dataStore.storeSecret(appId, secret);
        }
        return secret;
    }

    /**
     * errcode == 0
     *
     * @return
     */
    private boolean isSuccess(Map<String, Object> result) {
        Object errcode = result.get("errcode");
        return errcode == null || errcode.equals(0);
    }

    @Data
    @AllArgsConstructor
    public static class WXUserInfo {
        private String openid;
        private String unionid;
    }
}
